﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using HWorld;
using HWorld.Networking;

namespace ROrganizer.Client
{
    public class ImdbGateway
    {
        public ImdbEntry Query(HashEntry entry, HNetworkChannel channel = null)
        {
            return new ImdbEntry
            {
                File = entry.File,
                InfoTimestamp = DateTime.Now,
                Info = this.Query(entry.Info.Link, channel)
            };
        }

        public ImdbInfo Query(HashProposal proposal, HNetworkChannel channel = null)
        {
            return this.Query(proposal.Link, channel: channel);
        }

        public ImdbInfo Query(string link, HNetworkChannel channel = null)
        {
            var session = new HNetworkSession(channel: channel);
            var url = String.Format(@"http://www.imdb.com/title/tt{0}/", link);

            using (var data = session.Get(url))
            {
                var document = data.GetDocument();
                var title = HQuery.On(document).Execute("head title").SelectMany(x => x.Descendants<HText>()).Select(x => x.Value.Trim()).FirstOrDefault();
                var rating = HQuery.On(document).Execute("div.general div.info div.starbar-meta b").SelectMany(x => x.Descendants<HText>()).Select(x => x.Value.Split('/')[0].Trim()).FirstOrDefault();
                var published = HQuery.On(document).Execute("div.info div.info-content a[href='/title/tt" + link + "/releaseinfo'").SelectMany(x => x.Owner.Descendants<HText>()).Select(x => String.Join(" ", x.Value.Trim().Split(' ').Take(3))).FirstOrDefault();
                var genres = HQuery.On(document).Execute("div.info div.info-content a[href]").Where(x => x.Attributes[HAttributeType.Hyperlink].StartsWith("/Sections/Genres/")).SelectMany(x => x.Descendants<HText>()).Select(x => x.Value.Trim()).ToArray();
                var keywords = HQuery.On(document).Execute("div.info div.info-content a[href]").Where(x => x.Attributes[HAttributeType.Hyperlink].StartsWith("/keyword/")).SelectMany(x => x.Descendants<HText>()).Select(x => x.Value.Trim()).ToArray();
                var tagline = HQuery.On(document).Execute("div.info div.info-content a[href='/title/tt" + link + "/taglines'").SelectMany(x => x.Owner.Descendants<HText>()).Select(x => x.Value.Trim()).FirstOrDefault();
                var plot = HQuery.On(document).Execute("div.info div.info-content a[href='/title/tt" + link + "/plotsummary'").SelectMany(x => x.Owner.Descendants<HText>()).Select(x => x.Value.Trim()).FirstOrDefault();

                var ratingValue = default(short?);
                var publishedDate = default(DateTime?);

                try
                {
                    ratingValue = String.IsNullOrWhiteSpace(rating) ? default(short?) : Convert.ToInt16(Decimal.Parse(rating, CultureInfo.InvariantCulture) * 10);
                }
                catch(FormatException)
                {
                }

                try
                {
                    publishedDate = String.IsNullOrWhiteSpace(published) ? default(DateTime?) : DateTime.Parse(published);
                }
                catch (FormatException)
                {
                    var match = Regex.Match(published, @"((?<month>(January|February|March|April|May|June|July|August|September|October|November|December))|(?<year>[0-9]{4})|\s)*", RegexOptions.IgnoreCase);
                    
                    if (match.Groups["year"].Value.Length == 4)
                    {
                        publishedDate = new DateTime(Int32.Parse(match.Groups["year"].Value), 1, 1);

                        switch (match.Groups["month"].Value.ToLower())
                        {
                            case "february": publishedDate = publishedDate.Value.AddMonths(1); break;
                            case "march": publishedDate = publishedDate.Value.AddMonths(2); break;
                            case "april": publishedDate = publishedDate.Value.AddMonths(3); break;
                            case "may": publishedDate = publishedDate.Value.AddMonths(4); break;
                            case "june": publishedDate = publishedDate.Value.AddMonths(5); break;
                            case "july": publishedDate = publishedDate.Value.AddMonths(6); break;
                            case "august": publishedDate = publishedDate.Value.AddMonths(7); break;
                            case "september": publishedDate = publishedDate.Value.AddMonths(8); break;
                            case "october": publishedDate = publishedDate.Value.AddMonths(9); break;
                            case "november": publishedDate = publishedDate.Value.AddMonths(10); break;
                            case "december": publishedDate = publishedDate.Value.AddMonths(11); break;
                        }
                    }
                }

                return new ImdbInfo
                {
                    Id = link,
                    Title = title,
                    Rating = ratingValue,
                    Published = publishedDate,
                    Genres = genres,
                    Keywords = keywords,
                    Tagline = tagline ?? String.Empty,
                    Plot = plot ?? String.Empty
                };
            }
        }
    }
}
